package jp.tkym.labs.proc;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jp.tkym.labs.proc.PreparedJavaw.PrecallProcessLounch;
import jp.tkym.labs.proc.PreparedJavaw.PreparedJavawAdmin;


/**
 * Java Process Launcher 
 * @author takayama
 */
public class Javaw{
	private static final String DEFAULT_JAVA_CMD = "javaw";
	private final String javaw;
	private Map<String, String> environment = new HashMap<String, String>();
	private String classpath = System.getProperty("java.class.path");
	private String xmx = 512 + "m";
	private String xms = 128 + "m";
	
	private Javaw(String javaw){
		this.javaw = javaw;
	}
	
	public static PreparedJavawAdmin preparedAdmin(){
		return PreparedJavaw.getInstance().admin();
	}
	
	public static PrecallProcessLounch prepared() throws Exception{
		return PreparedJavaw.getInstance().launch();
	}
	
	public static Javaw create(String javaw){
		return new Javaw(javaw);
	}
	
	public static Javaw create(){
		return new Javaw(DEFAULT_JAVA_CMD);
	}
	
	public Javaw classpath(String classpath){
		this.classpath = classpath;
		return this;
	}
	
	public Javaw xmx(int size, String unit){
		this.xmx = size + unit;
		return this;
	}

	public Javaw xms(int size, String unit){
		this.xms = size + unit;
		return this;
	}
	
	public JavaProcessWorker main(Class<?> main) throws Exception{
		return launch().main(main);
	}
	
	public Javaw environment(Map<String, String> map) {
		environment.putAll(map);
		return this;
	}

	public Javaw env(String key, String value) {
		environment.put(key, value);
		return this;
	}
	
	public JavaProcessLaunch _D(String key, String value){
		return launch()._D(key, value);
	}
	
	public JavaProcessLaunch option(Map<String, String> _D){
		return launch().option(_D);
	}
	
	JavaProcessLaunch launch(){
		return new DefaultJavaProcessLaunch(
				javaw,
				"-classpath",this.classpath,
				"-Xmx"+this.xmx,
				"-Xms"+this.xms).environment(environment);
	}
	
	static class DefaultJavaProcessLaunch extends AbstractJavaProcessLounch{
		private List<String> command;
		private Map<String, String> environment = new HashMap<String, String>();

		private DefaultJavaProcessLaunch(String... cmd){
			command = Arrays.asList(cmd);
		}
		
		DefaultJavaProcessLaunch environment(Map<String, String> environment){
			this.environment = environment;
			return this;
		}
		
		@Override
		public JavaProcessWorker main(Class<?> main) throws IOException{
			List<String> cmd = new ArrayList<String>(this.command);
			cmd.addAll(optionCommand());
			cmd.add(main.getName());
			ProcessBuilder builder = new ProcessBuilder(cmd);
			builder.environment().putAll(this.environment);
			builder.redirectErrorStream(true);
			return new JavaProcessWorker(builder.start());
		}
		
		private List<String> optionCommand(){
			List<String> cmd = new ArrayList<String>();
			for(String key : option().keySet())
				if(option().get(key) != null)
					cmd.add("-D"+key+"="+encloseDoubleQuotes(option().get(key)));
			return cmd;
		}
		
		static String encloseDoubleQuotes(String source){
			if(source.startsWith("\"") && source.endsWith("\""))
				return source;
			return "\"" + source + "\"";
		}
	}
}